// 引入 axios
// 创建 axios 实例
// 拦截器
// 抛出实例
import axios from 'axios'
import store from '@/store'
import router from '@/router'
// 基础地址，超时时间   ===> 已完成
// 请求拦截器-统一注入token
// 响应拦截器-解构数据-处理异常
import { Loading, Message } from 'element-ui'
const pendingMap = new Map()
// baseURL 最好根据环境可以自己改变对应值 ===>
// 1.开发环境  /api
// 2.线上环境  /prod-api
// 如何来解决 ===> 环境变量的配置
// 配置 ===>  环境文件来配置 ===> 自定义 VUE_APP_BASE_自定义的字段
//           NODE_ENV ===> 默认值 就是当前的环境 ===> 表示环境的变量
// 取值 ===> process.env ===> node 提供的一个变量

// const request = axios.create({
//   baseURL: process.env.VUE_APP_BASE_API,
//   timeout: 5000
// })

const LoadingInstance = {
  _target: null,
  _count: 0
}

// 自定义配置
const custom_options = Object.assign(
  {
    repeat_request_cancel: false, // 是否开启取消重复请求, 默认为 true
    loading: false, // 是否开启loading层效果, 默认为false
    reduct_data_format: true, // 是否开启简洁的数据结构响应, 默认为true
    error_message_show: true, // 是否开启接口错误信息展示,默认为true
    code_message_show: true // 是否开启code不为10000时的信息提示, 默认为false
  }
)

const request = axios.create({
  baseURL: '/shuzhongtianApi',
  // baseURL: process.env.VUE_APP_BASE_API,
  timeout: 30000
})

request.interceptors.request.use(config => {
  // token 统一注入 Authorization
  removePending(config)
  custom_options.repeat_request_cancel && addPending(config)
  // 创建loading实例
  if (custom_options.loading) {
    LoadingInstance._count++
    if (LoadingInstance._count === 1) {
      LoadingInstance._target = Loading.service()
    }
  }
  const token = store.getters.userInfo.token
  // console.log(token)

  if (token) {
    config.headers.Token = token
  }
  return config
}, err => {
  return Promise.reject(err)
})

request.interceptors.response.use(response => {
  // 响应拦截器-解构数据-处理异常
  // 接口状态 200 ===>
  // 1.业务逻辑正常（success: true）
  // 2.业务逻辑出现问题 (success: false)
  // console.log(response.data)
  removePending(response.config)
  custom_options.loading && closeLoading(custom_options) // 关闭loading

  if (response.data instanceof ArrayBuffer) { return response.data }
  // console.log(response)
  const res = response.data
  const { msg } = res
  if (res.success || response.status === 200) {
    return res
  } else {
    // 提示
    // Promise.reject
    Message({ type: 'error', msg })
    return Promise.reject(new Error(msg))
  }

  // return response.data // axios 默认给我包一层data
  // err 只有接口正在报错的时候 才会进
  // console.dir(err)
  // 判断错误类型 ===> 401
  // 本地token删除 / 用户信息删除
  // 去登录页
  // 提示
}, error => {
  error.config && removePending(error.config)
  custom_options.loading && closeLoading(custom_options) // 关闭loading
  custom_options.error_message_show && httpErrorStatusHandle(error) // 处理错误状态码
  return Promise.reject(error) // 错误继续返回给到具体页面
})

export default request // 导出axios实例

/**
 * 处理异常
 * @param {*} error
 */
function httpErrorStatusHandle (error) {
  // 处理被取消的请求
  if (axios.isCancel(error)) {
    return console.error('请求的重复请求：' + error.message)
  }
  let message = ''
  if (error && error.response) {
    switch (error.response.status) {
      case 302:
        message = '接口重定向了！'
        break
      case 400:
        message = '参数不正确！'
        break
      case 401:
        store.commit('user/removeUserInfo')
        Message({ type: 'error', message: '你的登录状态已经失效，请重新登录' })
        router.push('/shuzhongtian/login')
        return

      case 403:
        message = '您没有权限操作！'
        break
      case 404:
        message = `请求地址出错: ${error.response.config.url}`
        break // 在正确域名下
      case 408:
        message = '请求超时！'
        break
      case 409:
        message = '系统已存在相同数据！'
        break
      case 500:
        message = '500服务器内部错误！'
        break
      case 501:
        message = '服务未实现！'
        break
      case 502:
        message = '网关错误！'
        break
      case 503:
        message = '系统升级中！'
        break
      case 504:
        message = '服务暂时无法访问，请稍后再试！'
        break
      case 505:
        message = 'HTTP版本不受支持！'
        break
      default:
        message = '异常问题，请联系管理员！'
        break
    }
  }
  if (error.message.includes('timeout')) message = '网络请求超时！'
  if (error.message.includes('Network')) {
    message = window.navigator.onLine ? '服务端异常！' : '您断网了！'
  }

  Message({
    type: 'error',
    message
  })
}

/**
 * 关闭Loading层实例
 * @param {*} _options
 */
function closeLoading (_options) {
  if (_options.loading && LoadingInstance._count > 0) LoadingInstance._count--
  if (LoadingInstance._count === 0) {
    LoadingInstance._target.close()
    LoadingInstance._target = null
  }
}

/**
 * 储存每个请求的唯一cancel回调, 以此为标识
 * @param {*} config
 */
function addPending (config) {
  const pendingKey = getPendingKey(config)
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken(cancel => {
      if (!pendingMap.has(pendingKey)) {
        pendingMap.set(pendingKey, cancel)
      }
    })
}

/**
 * 删除重复的请求
 * @param {*} config
 */
function removePending (config) {
  const pendingKey = getPendingKey(config)
  if (pendingMap.has(pendingKey)) {
    const cancelToken = pendingMap.get(pendingKey)
    // 如你不明白此处为什么需要传递pendingKey可以看文章下方的补丁解释
    cancelToken(pendingKey)
    pendingMap.delete(pendingKey)
  }
}

/**
 * 生成唯一的每个请求的唯一key
 * @param {*} config
 * @returns
 */
function getPendingKey (config) {
  // eslint-disable-next-line prefer-const
  let { url, method, params, data } = config
  if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
  return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
}
